package com.tools.service.license.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.tools.pojo.license.License;
import com.tools.pojo.license.LicenseVerifyResult;
import com.tools.service.license.LicenseService;
import com.tools.utils.HardwareUtil;
import com.tools.utils.RSAUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.time.LocalDate;

@Service
@Slf4j
public class LicenseServiceImpl implements LicenseService {



    @Resource
    private RSAUtil rsaUtil;

    @Resource
    private HardwareUtil hardwareUtil;

    @Resource
    private ObjectMapper objectMapper;

    @Override
    public String generateLicense(License license, PrivateKey privateKey) throws Exception {
        // 自动填充硬件指纹
        if (license.getHardwareId() == null || license.getHardwareId().isEmpty()) {
            String hardwareId = hardwareUtil.getMotherboardSerial();
            license.setHardwareId(hardwareId);
            log.info("自动获取硬件指纹: {}", hardwareId);
        }

        // 创建标准化的JSON数据用于签名
        String licenseData = createStandardizedLicenseJson(license);
        log.debug("待签名的许可证数据: {}", licenseData);

        // 使用私钥对许可证数据进行签名
        String signature = rsaUtil.sign(licenseData, privateKey);

        // 创建包含签名的完整许可证
        JsonNode jsonNode = objectMapper.readTree(licenseData);
        ((ObjectNode) jsonNode).put("signature", signature);

        String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
        log.info("许可证生成成功，授权给: {}, 到期时间: {}",
                license.getIssuedTo(), license.getExpireAt());
        return result;
    }

    @Override
    public LicenseVerifyResult verifyLicense(String licenseJson, PublicKey publicKey) {
        try {
            JsonNode jsonNode = objectMapper.readTree(licenseJson);

            // 检查是否包含签名字段
            if (!jsonNode.has("signature")) {
                return new LicenseVerifyResult(false, "许可证缺少数字签名");
            }
            String signature = jsonNode.get("signature").asText();

            // 移除签名字段，重构原始许可证数据
            ((ObjectNode) jsonNode).remove("signature");
            License license = objectMapper.readValue(jsonNode.toString(), License.class);

            // 重新生成标准化的JSON数据用于验证
            String licenseData = createStandardizedLicenseJson(license);
            log.debug("验证用许可证数据: {}", licenseData);

            // 验证数字签名
            boolean signatureValid = rsaUtil.verify(licenseData, signature, publicKey);
            if (!signatureValid) {
                log.warn("许可证数字签名验证失败");
                return new LicenseVerifyResult(false, "许可证数字签名无效");
            }

            // 验证硬件指纹
            String currentHardwareId = hardwareUtil.getMotherboardSerial();
            if (!currentHardwareId.equals(license.getHardwareId())) {
                log.warn("硬件指纹不匹配 - 期望: {}, 实际: {}",
                        license.getHardwareId(), currentHardwareId);
                return new LicenseVerifyResult(false,
                        String.format("硬件指纹不匹配。许可证绑定设备: %s, 当前设备: %s",
                                license.getHardwareId(), currentHardwareId));
            }

            // 验证许可证有效期
            if (license.getExpireAt().isBefore(LocalDate.now())) {
                log.warn("许可证已过期 - 到期时间: {}, 当前时间: {}",
                        license.getExpireAt(), LocalDate.now());
                return new LicenseVerifyResult(false,
                        String.format("许可证已过期。到期时间: %s, 当前时间: %s",
                                license.getExpireAt(), LocalDate.now()));
            }

            log.info("许可证验证通过 - 授权对象: {}, 功能权限: {}",
                    license.getIssuedTo(), license.getFeatures());
            return new LicenseVerifyResult(true, "许可证验证成功", license);

        } catch (Exception e) {
            log.error("许可证验证过程发生异常", e);
            return new LicenseVerifyResult(false, "许可证格式错误: " + e.getMessage());
        }
    }



    /**
     * 创建标准化的许可证JSON数据
     * 手动构建JSON确保字段顺序一致，这是签名验证成功的关键
     */
    private String createStandardizedLicenseJson(License license) {
        StringBuilder json = new StringBuilder();
        json.append("{");
        json.append("\"subject\":\"").append(escapeJson(license.getSubject())).append("\",");
        json.append("\"issuedTo\":\"").append(escapeJson(license.getIssuedTo())).append("\",");
        json.append("\"hardwareId\":\"").append(escapeJson(license.getHardwareId())).append("\",");
        json.append("\"expireAt\":\"").append(license.getExpireAt().toString()).append("\",");
        json.append("\"features\":[");

        if (license.getFeatures() != null && !license.getFeatures().isEmpty()) {
            for (int i = 0; i < license.getFeatures().size(); i++) {
                if (i > 0) json.append(",");
                json.append("\"").append(escapeJson(license.getFeatures().get(i))).append("\"");
            }
        }

        json.append("]}");
        return json.toString();
    }


    /**
     * 转义JSON字符串中的特殊字符
     */
    private String escapeJson(String str) {
        if (str == null) return "";
        return str.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }


}
